﻿using System;


namespace DailyFx.IndicatorExtension
{
    public class RSI : Index
    {
		private const int cPeriod = 14;


        /// <summary>
        /// c'tor
        /// </summary>
           public RSI ( int n ) 
               : base ( 1, n)
            {
			   this.Index = new HyperVector( n, "RSI", Layout.SLAVE, Stylus.LINE, 0);
            }


            public override void Cook ( BarSeries series )
            {

                decimal rsi = 0.0m;

                decimal gain = 0.0m;
                decimal loss = 0.0m;

                decimal delta = 0.0m;

				// 

                for (int i = 1; i < cPeriod; i++)    // unstable period skipping
                {
                    decimal diff = series[i].LastPx - series[i-1].LastPx;

                    if (diff > 0.0m)
                    {
                        gain += diff;
                    }
                    else if (diff < 0.0m)
                    {
                        loss += -diff;
                    }
                    else
                    {   // zero 
                    }

                    decimal s = (gain / i);
                    decimal r = (gain / i) + (loss / i);

                    if ( Math2.SloppyEquals(r, 0.0m))
                    {
                        rsi = 0.0m;
                    }
                    else // okey
                    {
                        rsi = 100.0m * (s / r);
                    }

					this.Index[i] = rsi;

                }

				for (int n = cPeriod; n < Length; n++)   // smooth
                {
                    //
					decimal diff = series[n].LastPx - series[n - 1].LastPx;
                    
					if (diff > 0.0m)
                    {
                        gain += diff;
                    }
                    else if (diff < 0.0m)
                    {
                        loss += -diff;
                    }
                    else
                    {   // skip zero .. 
                    }

                    if (delta > 0.0m)
                    {
                        gain -= delta;
                    }
                    else if (delta < 0.0m)
                    {
                        loss -= -delta;
                    }
                    else
                    {   // skip zero .. 
                    }

                    decimal s = (gain / cPeriod);
                    decimal r = (gain / cPeriod) + (loss / cPeriod);

                    if ( Math2.SloppyEquals(r, 0.0m) )
                    {
                        rsi = 0.0m;
                    }
                    else // okey
                    {
                        rsi = 100.0m * (s / r);
                    }
                    //
                    delta = series [n- cPeriod].LastPx - series[n - cPeriod - 1].LastPx;

					this.Index[n] = rsi;
                }
            }


            public override string Family
            {
                get { return "Relative Strength Index"; }
            }

            public override string Label
            {
                get { return "RSI"; }
            }


         

			public HyperVector Index 
			{
				get {
					return _children[0];
				}
				private set {
					_children[0] = value;
				}
			}

	} // ks RSI

} // 